package com.opencee.cloud.msg.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.opencee.cloud.msg.api.constatns.MsgChannelSp;
import com.opencee.cloud.msg.api.constatns.MsgChannelType;
import com.opencee.cloud.msg.api.constatns.MsgConstants;
import com.opencee.cloud.msg.api.entity.MsgChannelConfigEntity;
import com.opencee.cloud.msg.api.vo.MsgChannelConfigVO;
import com.opencee.cloud.msg.mapper.MsgChannelConfigMapper;
import com.opencee.cloud.msg.service.MsgChannelConfigService;
import com.opencee.cloud.msg.service.impl.push.GeTuiSdk;
import com.opencee.cloud.msg.service.impl.push.JPushSdk;
import com.opencee.cloud.msg.service.impl.sms.AliyunSdk;
import com.opencee.cloud.msg.service.impl.sms.TencentSdk;
import com.opencee.common.utils.RedisTemplateUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Properties;
import java.util.concurrent.TimeUnit;

/**
 * @author liuyadu
 * @date 2022/2/8
 */
@Service
public class MsgChannelConfigServiceImpl extends SupperServiceImpl<MsgChannelConfigMapper, MsgChannelConfigEntity> implements MsgChannelConfigService {
    @Autowired
    private RedisTemplateUtil redisTemplateUtil;

    /**
     * 通过通道id获取信息
     *
     * @param id
     * @return
     */
    @Override
    public MsgChannelConfigVO getById(Long id) {
        String key = MsgConstants.CACHE_CHANNEL_KEY + id;
        if (redisTemplateUtil.hasKey(key)) {
            return (MsgChannelConfigVO) redisTemplateUtil.get(key);
        }
        MsgChannelConfigEntity entity = this.getById(id);
        MsgChannelConfigVO vo = null;
        if (entity != null) {
            vo = new MsgChannelConfigVO();
            BeanUtils.copyProperties(entity, vo);
            redisTemplateUtil.set(key, vo, 2, TimeUnit.HOURS);
        } else {
            redisTemplateUtil.set(key, vo, 1, TimeUnit.MINUTES);
        }
        return vo;
    }

    /**
     * 添加
     *
     * @param config
     * @return
     */
    @Override
    public boolean save(MsgChannelConfigVO config) {
        this.validate(config);
        MsgChannelType channelType = MsgChannelType.getByValue(config.getChannelType());
        String key = channelType.name().toUpperCase() + "_" + IdUtil.objectId();
        config.setChannelKey(key);
        MsgChannelConfigEntity entity = new MsgChannelConfigEntity();
        BeanUtils.copyProperties(config, entity);
        entity.setContent(config.getContentObject().toJSONString());
        return baseMapper.insert(entity) > 0;
    }

    /**
     * 更新
     *
     * @param config
     * @return
     */
    @Override
    public boolean update(MsgChannelConfigVO config) {
        this.validate(config);
        MsgChannelConfigEntity saved = getById(config.getId());
        Assert.notNull(saved, "通道信息不存在");
        MsgChannelConfigEntity entity = new MsgChannelConfigEntity();
        BeanUtils.copyProperties(config, entity);
        entity.setChannelKey(null);
        entity.setContent(config.getContentObject().toJSONString());
        boolean flag = baseMapper.updateById(entity) > 0;
        if (flag) {
            String idKey = MsgConstants.CACHE_CHANNEL_ID + config.getId();
            String key = MsgConstants.CACHE_CHANNEL_KEY + config.getChannelKey();
            redisTemplateUtil.del(idKey, key);
        }
        return flag;
    }

    /**
     * 通过通道key获取信息
     *
     * @param channelKey
     * @return
     */
    @Override
    public MsgChannelConfigVO getByKey(String channelKey) {
        String key = MsgConstants.CACHE_CHANNEL_KEY + channelKey;
        if (redisTemplateUtil.hasKey(key)) {
            return (MsgChannelConfigVO) redisTemplateUtil.get(key);
        }
        QueryWrapper<MsgChannelConfigEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(MsgChannelConfigEntity::getChannelKey, channelKey);
        MsgChannelConfigEntity entity = this.getOne(queryWrapper);
        MsgChannelConfigVO vo = null;
        if (entity != null) {
            vo = new MsgChannelConfigVO();
            BeanUtils.copyProperties(entity, vo);
            redisTemplateUtil.set(key, vo, 2, TimeUnit.HOURS);
        } else {
            redisTemplateUtil.set(key, vo, 1, TimeUnit.MINUTES);
        }
        return vo;
    }

    /**
     * 验证配置信息
     *
     * @param config
     * @return
     */
    @Override
    public void validate(MsgChannelConfigVO config) {
        Assert.hasText(config.getChannelName(), "通道名称不能为空");
        Assert.notNull(config.getChannelType(), "通道类型不能为空");
        MsgChannelType channelType = MsgChannelType.getByValue(config.getChannelType());
        Assert.notNull(channelType, "类型不支持:" + config.getChannelType());
        MsgChannelSp channelSp = MsgChannelSp.getByValue(config.getChannelSp());
        Assert.notNull(channelSp, "服务提供商不支持:" + config.getChannelSp());
        JSONObject content = config.getContentObject();
        if (channelType.equals(MsgChannelType.EMAIL)) {
            Assert.hasText(content.getString("host"), "host不能为空");
            Assert.hasText(content.getString("username"), "username不能为空");
            Assert.hasText(content.getString("password"), "password不能为空");
            Assert.hasText(content.getString("port"), "port不能为空");
            Properties properties = new Properties();
            properties.putAll(content.getJSONObject("properties"));
            Assert.notNull(properties, "缺少properties配置");
            if (!properties.containsKey("mail.smtp.socketFactory.class")) {
                properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
            }
            config.getContentObject().put("properties", properties);
        }

        if (channelType.equals(MsgChannelType.PUSH)) {
            if (channelSp.equals(MsgChannelSp.GETUI)) {
                GeTuiSdk sdk = config.getContentObject().toJavaObject(GeTuiSdk.class);
                Assert.hasText(sdk.getAppId(), "appId不能为空");
                Assert.hasText(sdk.getAppKey(), "appKey不能为空");
                Assert.hasText(sdk.getAppSecret(), "appSecret不能为空");
                Assert.hasText(sdk.getMasterSecret(), "masterSecret不能为空");
            }
            if (channelSp.equals(MsgChannelSp.JPUSH)) {
                JPushSdk sdk = config.getContentObject().toJavaObject(JPushSdk.class);
                Assert.hasText(sdk.getAppKey(), "appKey不能为空");
                Assert.hasText(sdk.getAppSecret(), "appSecret不能为空");
            }
        }

        if (channelType.equals(MsgChannelType.SMS)) {
            if (channelSp.equals(MsgChannelSp.ALIYUN)) {
                AliyunSdk sdk = config.getContentObject().toJavaObject(AliyunSdk.class);
                Assert.hasText(sdk.getappKeyId(), "appKeyId不能为空");
                Assert.hasText(sdk.getappSecret(), "appSecret不能为空");
                Assert.hasText(sdk.getRegion(), "region不能为空");
            }
            if (channelSp.equals(MsgChannelSp.TENCENT)) {
                TencentSdk sdk = config.getContentObject().toJavaObject(TencentSdk.class);
                Assert.hasText(sdk.getAppId(), "appId不能为空");
                Assert.hasText(sdk.getappKeyId(), "appKeyId不能为空");
                Assert.hasText(sdk.getappSecret(), "appSecret不能为空");
                Assert.hasText(sdk.getRegion(), "region不能为空");
            }
        }
    }
}
